package com.lzq.framework.core.aop;

import com.lzq.framework.core.annotation.SendErrorEmail;
import com.lzq.framework.util.time.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.util.Date;

/**
 * @author 2019/3/21 10:46 by 刘赵强
 **/
@Aspect
@Component
public class SendErrorEmailAspect {
    private Logger logger = LoggerFactory.getLogger(SendErrorEmailAspect.class);

    /**
     * AOP异常通知
     *
     * @param joinPoint 切入点
     * @param ex        异常
     */
    @AfterThrowing(value = "@annotation(com.lzq.framework.core.annotation.SendErrorEmail)", throwing = "ex")
    public void interceptor(JoinPoint joinPoint, Exception ex) {
        try {
            String methodName = joinPoint.getSignature().getName();
            SendErrorEmail sendErrorEmailAnnotation = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(SendErrorEmail.class);
            String msg = sendErrorEmailAnnotation.msg();
            String date = DateUtil.formatDate(new Date(), DateUtil.YYYYMMDDHH_MM_SS);
            boolean printStackTrace = sendErrorEmailAnnotation.printStackTrace();
            //错误信息
            String errMsg = getErrMsg(printStackTrace, msg, ex);
            String params = getParams(joinPoint);
            //TODO 邮件发送
            //EmailUtil.sendErrorEmail(date, methodName, errMsg, params);
        } catch (Exception e) {
            logger.error("发送异常短信的AOP异常通知处理异常errorMsg={}", e.getMessage(), e);
        }
    }

    /**
     * 获取异常信息
     *
     * @param printStackTrace 是否打印堆栈信息
     * @param msg             自定义信息
     * @param ex              异常
     * @return 返回组合异常
     */
    private String getErrMsg(boolean printStackTrace, String msg, Exception ex) {
        if (printStackTrace && StringUtils.isNotEmpty(msg)) {
            return msg + "<br/>" + ex.getMessage() + "<br/>" + getErrorStackTraceStr(ex);
        } else if (printStackTrace) {
            return ex.getMessage() + "<br/>" + getErrorStackTraceStr(ex);
        } else if (StringUtils.isNotEmpty(msg)) {
            return msg + "<br/>" + ex.getMessage();
        } else {
            return ex.getMessage();
        }
    }


    /**
     * @param ex 异常
     * @return 获取异常堆栈信息
     */
    private String getErrorStackTraceStr(Exception ex) {
        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        ex.printStackTrace(new java.io.PrintWriter(buf, true));
        return buf.toString();
    }

    /**
     * @param joinPoint 截取点
     * @return 获取参数和参数名拼接的字符串
     */
    private String getParams(JoinPoint joinPoint) {
        Object[] paramValues = joinPoint.getArgs();
        String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();

        //获取被切参数名称及参数值
        StringBuilder paramBuilder = new StringBuilder();
        for (int i = 0; i < paramNames.length; i++) {
            paramBuilder.append("&").append(paramNames[i]).append("=").append(paramValues[i]);
        }
        if (paramBuilder.length() > 0) {
            return paramBuilder.substring(1);
        }
        return "";
    }
}
